#pragma once
#include <iostream>
#include <queue>
#include<pthread.h>

using namespace std;

static const int defaultcap = 10;
template <class T>
class BlockQueue
{
public:
    BlockQueue(int cap = defaultcap) : cap_(cap)
    {
        pthread_mutex_init(&lock_, nullptr);
        pthread_cond_init(&c_cond_, nullptr);
        pthread_cond_init(&p_cond_, nullptr);
    }
    ~BlockQueue()
    {
        pthread_mutex_destroy(&lock_);
        pthread_cond_destroy(&c_cond_);
        pthread_cond_destroy(&p_cond_);
    }
    void Push(const T &in)
    {
        pthread_mutex_lock(&lock_);
        // 判断队列的容量
        while (qt_.size() == cap_)
        {
            // 进入条件变量下等待
            pthread_cond_wait(&p_cond_, &lock_);
        }
        qt_.push(in);
        pthread_cond_signal(&c_cond_);
        pthread_mutex_unlock(&lock_);
    }
    T Pop()
    {
        pthread_mutex_lock(&lock_);

        while (qt_.empty())
        {
            pthread_cond_wait(&c_cond_, &lock_);
        }
        T out = qt_.front();
        qt_.pop();
        pthread_cond_signal(&p_cond_);
        pthread_mutex_unlock(&lock_);
        return out;
    }

private:
    int cap_;
    queue<T> qt_;

    
    pthread_mutex_t lock_;
    pthread_cond_t c_cond_;
    pthread_cond_t p_cond_;
};
